#pragma once

#include "fxcc/core/graph/common/pch.h"
#include "fxcc/core/graph/common/MaterialView.h"

#include "glslang/Public/ResourceLimits.h"
#include <glslang/MachineIndependent/localintermediate.h>
#include <StandAlone/DirStackFileIncluder.h>
#include <StandAlone/Worklist.h>

namespace fxcc::graph::common
{

    struct GlslShader
    {
        struct Type
        {
            glslang::TBasicType m_BasicType{ glslang::TBasicType::EbtVoid };
            glslang::TSampler m_Sampler;
            glslang::TQualifier m_Qualifier;

            int m_VectorSize{ 0 };

            Type() {}

            Type(const glslang::TType* type);

        };
        struct ShaderStage
        {
            std::string m_ShaderCode;
            EShLanguage m_Stage;
        };


        struct UniformVariable
        {
            std::string m_Name;
            int m_Binding{ -1 };
            int m_LayoutLocation{ -1 };
            int m_Offset{ 0 };

            GlslShader::Type m_Type;

            void Influence(fxcc::graph::common::MaterialView& material) const;

        };
        struct UniformBlock
        {
            std::string m_Name;
            int m_Binding{ -1 };
            int m_Index{ -1 };
            int m_Size{ 0 };

            GlslShader::Type m_Type;

        };
        std::vector<ShaderStage> m_ShaderStages;
        std::vector<UniformVariable> m_UniformVariables;
        std::vector<UniformBlock> m_UniformBlocks;

        void Clear()
        {
            m_ShaderStages.clear();
            m_UniformBlocks.clear();
            m_UniformBlocks.clear();
        }

        void addShader(const std::string& shaderCode, EShLanguage stage)
        {
            ShaderStage shaderStage;
            shaderStage.m_ShaderCode = shaderCode;
            shaderStage.m_Stage = stage;
            m_ShaderStages.push_back(shaderStage);

        }
        void addFragShader(const std::string& shaderCode)
        {
            ShaderStage shaderStage;
            shaderStage.m_ShaderCode = shaderCode;
            shaderStage.m_Stage = EShLanguage::EShLangFragment;
            m_ShaderStages.push_back(shaderStage);

        }
        std::vector<std::shared_ptr<glslang::TShader>> m_TShaders;

        void Build();

        void InfluenceMaterial(fxcc::graph::common::MaterialView& material) const;

        static const TBuiltInResource GlslShader::DefaultTBuiltInResource;

        static bool IsMaterialVariable(const std::string& name);
    };

};
